Skip to content

build: update the Kubernetes client - #178

Merged
uniqueg merged 10 commits into
devfrom
build/164-kubernetes-client
Nov 14, 2026
Merged

uniqueg merged 10 commits into
devfrom
build/164-kubernetes-client

Conversation

@uniqueg

@uniqueg uniqueg commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

Summary

Updates io.kubernetes:client-java from 11.0.4 to 28.0.0 (Kubernetes 1.37), still on Spring Boot 2.7 and Java 21, and moves to SnakeYAML 2.

  • Dependencies (pom.xml): the client, plus the libraries it needs in newer versions than Spring Boot 2.7 manages, set to those of the client's parent POM: SnakeYAML 2.7, OkHttp 5.5.0, Kotlin 2.1.21, Gson 2.14.0, Commons Lang 3.21.0, Commons Codec 1.23.0. The pins of protobuf-java, commons-io and commons-compress are dropped: the client resolves to the same versions (4.36.2, 2.22.0, 1.28.0). With refactor: use Spring Security's resource server #175 merged, spring-security-jwt and its Bouncy Castle *-jdk15on 1.70 jars are gone, so only the client's *-jdk18on 1.86 jars are on the classpath (no exclusion needed).
  • Code: KubernetesClientWrapper and KubernetesObjectsSupplier use the client's request-builder API. The models use java.time instead of Joda-Time. ServiceInfoService passes LoaderOptions, which SnakeYAML 2 needs.
  • Unknown fields (KubernetesJson): since version 20, the client's models refuse JSON with fields they don't know, so any object that a newer Kubernetes version extends would fail to read (kubernetes-client/java#4941). KubernetesClientConfig installs a Gson that ignores unknown fields, as client 11 and client-go do. TESK API only reads objects and creates or patches its own, so it loses nothing.
  • Empty collections: the new models start with empty lists and maps. The executors' jobs in the taskmaster's input are written without them (GSON_WITHOUT_EMPTY_COLLECTIONS), as before. This matters because the taskmaster copies the requests to the limits only when limits is missing, so with limits: {} a task with ram_gb but no cpu_cores would have run without a memory limit (caught in review; regression test ramOnlyExecutorHasNoLimits). Objects that TESK API sends to Kubernetes directly do list empty fields, which Kubernetes treats as unset.
  • Fix: the merge-patch client now keeps the Bearer prefix of a kubeconfig token. Before, patches (cancelling tasks) failed when TESK API ran outside a cluster with a token in its kubeconfig (regression test KubernetesClientConfigTest, which fails on 11.0.4).
  • Creation time: a job without creationTimestamp (Kubernetes always sets one) now gives a task without creation_time. Joda printed the current time instead.
  • Scan and Dependabot: the Trivy entry for CVE-2022-1471 (SnakeYAML 1.33) is gone, and so is the Dependabot hold on major versions of the client.
  • Docs: deployment (client version, Kubernetes compatibility, empty fields), development (library versions to update with the client, KubernetesJson), upgrade notes.

Spring Boot stays on 2.7 (#168/#169 are separate). dev with #175 is merged in (no rebase): the pom.xml conflict is resolved by keeping neither the removed pins nor the spring-security-oauth2 pin, and the Bouncy Castle exclusion and its note in the development docs went with spring-security-oauth2-autoconfigure.

Closes #164

Verification

  • ./mvnw verify on Java 21, after merging dev (refactor: use Spring Security's resource server #175): 18492 unit tests and 109 integration tests pass, and the JaCoCo coverage checks are met.

  • ./mvnw spotless:check checkstyle:check on Java 8 passes.

  • New tests:

    • KubernetesClientWrapperHttpTest runs the wrapper through a real client against WireMock and checks the query parameters, merge-patch bodies, pod logs, LimitRanges and errors.
    • KubernetesClientConfigTest covers the patch client's content type and token prefix.
    • KubernetesJsonTest covers unknown fields, missing required fields, times, Base64 data, the leaving out of empty collections, and the install.
    • TesKubernetesConverterMinimalTest adds ramOnlyExecutorHasNoLimits and fromK8sToTask_noCreationTime.
    • The converter tests keep their strict JSON assertions from dev.
  • docker build succeeds. The image starts and answers GET /service-info. The fat jar holds snakeyaml-2.7.jar and no SnakeYAML 1.x, and only the *-jdk18on Bouncy Castle jars.

  • CI: all checks pass (CI passed), including Test, Lint, Docs, Smoke test, and Scan image without the Trivy entry for SnakeYAML. CodeQL also passes.

  • End to end on kind (v0.33.0, Kubernetes node image of that release), after merging dev: the PR image with the tesk-core 0.11.0 taskmaster and filer, in its own namespace, with the edit role for the API's and the taskmaster's service accounts. All three checks pass:

    1. A simple task (echo) reaches COMPLETE, and its stdout is in the FULL view.
    2. A ram-only task (ram_gb: 0.25, no cpu_cores): the executor pod has limits.memory = requests.memory = 268435456, and the task completes. This is the case of the review finding fixed above.
    3. Cancelling a running task: state CANCELED, the taskmaster job is labelled Cancelled, and the executor stops.

    The script is outside the repository (it has no end-to-end suite yet): tesk-api-e2e-kind.sh in the maintainer's work folder; it builds the image, creates a throwaway cluster with its own kubeconfig, and deletes the cluster at the end. The cluster is deleted.

  • codecov/patch was at 98.76%: the read side of the new Gson adapter had no test; withoutEmptyCollectionsReads covers it now.

Declined review findings

  • Quality review, low: the hard-coded "Kubernetes 1.37" claim in docs/deployment.md. Kept: the v28.0.0 release notes of the client state it, and the docs name version 28 next to it.

Open questions

None.

🤖 Generated with Claude Code

Summary by Sourcery

Upgrade the Kubernetes client and its supporting dependencies while preserving TESK’s Kubernetes compatibility and correcting authentication and serialization edge cases.

Bug Fixes:

  • Preserve kubeconfig bearer-token prefixes for Kubernetes merge-patch requests.
  • Avoid generating incorrect task limits and creation times when Kubernetes data is missing.

Enhancements:

  • Upgrade the Kubernetes Java client to version 28 and align its required dependencies, including SnakeYAML 2.
  • Support Kubernetes objects with unknown fields and maintain compatible handling of empty collections and Java time values.
  • Update Kubernetes API integrations to the client’s request-builder interface.

Build:

  • Update dependency management for the Kubernetes client and its required library versions, including removal of obsolete version overrides.

Documentation:

  • Document Kubernetes client compatibility, serialization behavior, dependency maintenance, and upgrade impacts.

Tests:

  • Add coverage for Kubernetes client HTTP requests, authentication, JSON handling, serialization compatibility, and conversion edge cases.

Chores:

  • Remove the obsolete Dependabot hold for major Kubernetes client updates and the SnakeYAML vulnerability exception.

uniqueg and others added 7 commits November 14, 2026 02:56
Move io.kubernetes:client-java from 11.0.4 to 28.0.0 (Kubernetes
1.37), with SnakeYAML 2 instead of 1.33, and set the versions of
the libraries that the client needs and Spring Boot 2.7 manages
lower (OkHttp, Kotlin, Gson, Commons Lang, Commons Codec). Drop the
pins of protobuf-java, commons-io, commons-compress and
bcprov-ext-jdk15on: the client asks for the same versions, or
nothing needs them any more.

- Calls in KubernetesClientWrapper and KubernetesObjectsSupplier
  use the request-builder API; the models use java.time instead of
  Joda-Time.
- KubernetesJson: a Gson that ignores unknown fields, as the client
  did up to version 19, since its models now refuse objects of
  newer Kubernetes versions (kubernetes-client/java#4941).
- The merge-patch client keeps the "Bearer" prefix of a kubeconfig
  token, which it dropped, so patches failed outside a cluster.
- ServiceInfoService builds its YAML constructor with LoaderOptions
  (SnakeYAML 2).
- A task whose taskmaster job has no creation time gets none,
  rather than the current time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The image has SnakeYAML 2 now, so CVE-2022-1471 no longer needs an
entry in .trivyignore.yaml. Dependabot may propose major versions of
the Kubernetes client again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deployment: the client version, and the Kubernetes versions TESK API
works with. Development: the library versions to update with the
client, and KubernetesJson. Upgrade notes: what changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Kubernetes client brings bcprov/bcpkix-jdk18on 1.86, and
spring-security-jwt the jdk15on jars 1.70, which have the same
classes: the image had both. Exclude the jdk15on jars, whose pins
go too; spring-security-jwt only uses ASN.1 classes that jdk18on
has. Drop the unused apache.commons.lang3.version property.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
KubernetesClientWrapperHttpTest sends the wrapper's requests
through a real client to WireMock: query parameters (labelSelector,
continue, limit, dryRun, propagationPolicy), merge-patch bodies, pod
logs, LimitRanges and errors. KubernetesClientConfig installs the
lenient Gson in its constructor, which a test checks. Converter
tests strip empty fields only in the executors' jobs, with a test
of the helper. Docs: the creation time, the affected kubeconfigs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The models of client 28 start with empty lists and maps, so the
executors' jobs in the taskmaster's input had "limits": {} for a
task with ram_gb but no cpu_cores. The taskmaster sets the limits
to the requests only if there are none, so such executors ran
without a memory limit. Write the executors' jobs with a Gson that
leaves out empty lists and maps, as client 11 did, and restore the
strict assertions of the converter tests (and drop the helper that
stripped empty fields in them).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Data structures

Define the Kubernetes JSON serialization behavior needed by the upgraded models: tolerate unknown fields, preserve Kubernetes-specific adapters, and omit empty collections where taskmaster input requires their absence.

  • src/main/java/uk/ac/ebi/tsc/tesk/k8s/config/KubernetesJson.java L1-89

API

Adapt Kubernetes client configuration and calls to client 28’s request-builder API, install the lenient Gson, and preserve authentication when constructing the merge-patch client.

  • src/main/java/uk/ac/ebi/tsc/tesk/k8s/config/KubernetesClientConfig.java L18-25, L49-55, L82-86
  • src/main/java/uk/ac/ebi/tsc/tesk/k8s/convert/KubernetesObjectsSupplier.java L68-69
  • src/main/java/uk/ac/ebi/tsc/tesk/k8s/service/KubernetesClientWrapper.java L80-83, L183-188, L201-206 (+13 small edits)

Implementation

Apply the new Kubernetes serialization and java.time behavior when converting tasks, executor jobs, and Kubernetes timestamps.

  • src/main/java/uk/ac/ebi/tsc/tesk/config/GsonConfig.java L4 (removed lines), L6, L14
  • src/main/java/uk/ac/ebi/tsc/tesk/k8s/convert/TaskStateResolver.java L16, L27 (removed lines), L102-107
  • src/main/java/uk/ac/ebi/tsc/tesk/k8s/convert/TesKubernetesConverter.java L184-190, L616-620 (+8 small edits)

Update the service-info YAML constructor for SnakeYAML 2’s required LoaderOptions.

  • src/main/java/uk/ac/ebi/tsc/tesk/tes/service/ServiceInfoService.java L14, L78-79

Configuration

Upgrade the Kubernetes client and align dependency overrides with the versions required by its parent POM.

  • .trivyignore.yaml L8, L61 (removed lines)
  • pom.xml L38-45 (+4 small edits)
  • .github/dependabot.yml L19 (removed lines)

Documentation

Document the upgraded client’s Kubernetes compatibility, serialization behavior, dependency maintenance, and upgrade impact.

  • docs/deployment.md L59-73
  • docs/development.md L11-21
  • docs/upgrading.md L82-93

Tests

Verify Kubernetes JSON compatibility, merge-patch authentication, and real HTTP request behavior against WireMock.

  • src/test/java/uk/ac/ebi/tsc/tesk/k8s/config/KubernetesClientConfigTest.java L1-67
  • src/test/java/uk/ac/ebi/tsc/tesk/k8s/config/KubernetesJsonTest.java L1-120
  • src/test/java/uk/ac/ebi/tsc/tesk/k8s/service/KubernetesClientWrapperHttpTest.java L1-186

Update and extend tests for new client request builders, java.time values, missing creation times, and absent empty collections in executor input.

  • src/test/java/uk/ac/ebi/tsc/tesk/k8s/convert/IgnoredBackendParametersTest.java L94
  • src/test/java/uk/ac/ebi/tsc/tesk/k8s/convert/TaskStateResolverTest.java L17, L25 (removed lines), L600-605
  • src/test/java/uk/ac/ebi/tsc/tesk/k8s/convert/TesKubernetesConverterMinimalTest.java L59, L248-286, L600-608
  • src/test/java/uk/ac/ebi/tsc/tesk/k8s/convert/TesKubernetesConverterTest.java L123-127
  • src/test/java/uk/ac/ebi/tsc/tesk/k8s/service/KubernetesClientWrapperTest.java L54-89, L492-507, L650-659 (+47 small edits)
  • src/test/java/uk/ac/ebi/tsc/tesk/tes/service/TesServiceImplCreateTest.java L390

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@codecov

codecov Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.60%. Comparing base (73fb752) to head (e43f580).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #178      +/-   ##
==========================================
+ Coverage   76.82%   77.60%   +0.77%     
==========================================
  Files          73       74       +1     
  Lines        3439     3487      +48     
  Branches      412      416       +4     
==========================================
+ Hits         2642     2706      +64     
+ Misses        640      621      -19     
- Partials      157      160       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@uniqueg
uniqueg marked this pull request as ready for review November 14, 2026 02:28
@sourcery-ai

sourcery-ai Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

Linked issues

Checked at commit e43f580

#164 build: update the Kubernetes client · 7 of 8 met · 1 to check by hand

# Requirement Status Notes
1 Update client-java and migrate Kubernetes calls and tests to its request-builder API ✅ Met pom.xml upgrades client-java to 28.0.0; the wrapper, ConfigMap supplier, and affected tests use request builders.
2 Drop the SnakeYAML 1.33 pin and Trivy exception, and re-check the transitive dependency pins ✅ Met SnakeYAML is pinned to 2.7, the CVE-2022-1471 exception is removed, and the obsolete dependency pins are dropped or retained as appropriate.
3 Remove the Dependabot hold for io.kubernetes:client-java ✅ Met The client-java major-version ignore rule is removed.
4 Adjust integration tests for Kubernetes request paths and parameters ✅ Met KubernetesClientWrapperHttpTest exercises the updated requests against WireMock, including query parameters, patches, logs, and errors.
5 Document the client and its supported Kubernetes versions ✅ Met The deployment documentation names client version 28, its Kubernetes 1.37 support, and compatibility behavior with older and newer versions.
6 Have no SnakeYAML 1.x in the image and pass the scan without its exception ✅ Met The dependency is set to SnakeYAML 2.7, the exception is gone, and the PR reports that the image scan passes.
7 Pass unit and integration tests ✅ Met The PR reports that ./mvnw verify passed, including unit and integration tests.
8 Run a task end to end on a local cluster with the image 👀 Check by hand (runtime) The PR says this was not verified; run a task end to end with the image on a local kind or k3d cluster.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approval pending. The security scan did not finish.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

uniqueg and others added 3 commits November 14, 2026 17:50
…lient

Resolves pom.xml: #175 removed spring-security-oauth2 and its
autoconfigure, so the Bouncy Castle exclusion goes with them; the
removed pins stay removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
spring-security-jwt left with #175, so there are no older Bouncy
Castle jars left to keep out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Covers the read side of the adapter that leaves out empty
collections, the one line of the patch that no test ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@uniqueg
uniqueg merged commit 645acf7 into dev Nov 14, 2026
34 checks passed
@uniqueg
uniqueg deleted the build/164-kubernetes-client branch November 14, 2026 17:19
uniqueg added a commit that referenced this pull request Nov 14, 2026
Brings in #161, #174, #175, #176, #178, #181, #183 and #184. The
conflict in docs/upgrading.md is resolved by merging both lists under
"To 1.3.0": the upgrade order for filer labels and Java 21 come first,
and the TES 1.1 fields item no longer says that ignore_error: true is
refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
uniqueg added a commit that referenced this pull request Nov 14, 2026
Lists the changes merged into dev since the notes were written:
Java 21 (#161), ignore_error (#174), the resource server (#175),
output file logs (#176), the Kubernetes client (#178), Dependabot
labels (#181), the executor job selector (#183) and full test coverage
(#184). Adds a Breaking changes section, as in the 1.2.0 notes, and
sets date-released to the planned tag date, 2026-11-16.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build: update the Kubernetes client

1 participant